package org.jordens.jdbcspy.ui;

import org.jfree.beans.*;
import org.jfree.data.xy.*;
import org.jordens.jdbcspy.sync.*;

import javax.swing.*;
import java.awt.*;
import java.util.List;

/**
 * A basic line chart displaying the # of sql queries executed per second.
 *
 * @author Adam Jordens
 */
public class QueriesPerSecondPanel extends JPanel implements Resetable
{
    private final JLineChart chart = new JLineChart();
    private XYSeries numberOfSQLQueries;
    private XYSeries sqlExecutionTimes;

    private final QueriesPerSecondPanelUpdater panelUpdater =
            new QueriesPerSecondPanelUpdater();

    /**
     * @param dataStreamer Data source for this panel.
     */
    public QueriesPerSecondPanel(DataStreamer dataStreamer)
    {
        setup();
        dataStreamer.register(panelUpdater);
    }

    /**
     * Reset the underlying JDBCSpyMBean
     */
    public void reset()
    {
        numberOfSQLQueries.clear();
        sqlExecutionTimes.clear();
    }

    /**
     * Perform any necessary setup of this panel.
     */
    private void setup()
    {
        setLayout(new BorderLayout());
        setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));

        chart.setTitle("SQL Queries per Second");
        chart.setSubtitle("");
        add(chart, BorderLayout.CENTER);

        XYSeriesCollection dataset = new XYSeriesCollection();

        numberOfSQLQueries = new XYSeries("Number of SQL Queries");
        dataset.addSeries(numberOfSQLQueries);

        sqlExecutionTimes = new XYSeries("SQL Execution Time");
        dataset.addSeries(sqlExecutionTimes);

        chart.setDataset(dataset);
        chart.setXAxisLabel("Time (s)");
        chart.setYAxisLabel("# of Queries");
    }

    /**
     * DataUpdater that will periodically update the execution graph in response
     * to updates from the DataStreamer. 
     */
    private class QueriesPerSecondPanelUpdater implements DataUpdater
    {
        private final long startMS;

        /**
         * Constructs a new QueriesPerSecondPanelUpdater.
         */
        public QueriesPerSecondPanelUpdater()
        {
            this.startMS = System.currentTimeMillis();
        }

        /**
         * {@inheritDoc}
         */
        public void update(List<JDBCSpyRecord> jdbcSpyRecords)
        {
            double currentSeconds = (System.currentTimeMillis() - startMS) / 1000;

            for (JDBCSpyRecord jdbcSpyRecord : jdbcSpyRecords)
            {
                long queryCount = jdbcSpyRecord.getTotalQueryExecutionCount();
                numberOfSQLQueries.add(currentSeconds, queryCount);

                long sqlExecutionTime = jdbcSpyRecord.getTotalSQLExecutionTime();
                sqlExecutionTimes.add(currentSeconds, sqlExecutionTime);

                QueriesPerSecondPanel.this.revalidate();
                QueriesPerSecondPanel.this.repaint();
            }
        }

        /**
         * {@inheritDoc}
         */
        public void reset()
        {
            // do nothing
        }
    }
}
